package org.etherframework.tests.features.access
{
	import flash.system.ApplicationDomain;
	
	import mx.core.IVisualElement;
	
	import org.etherframework.core.IModule;
	import org.etherframework.tests.features.access.configs.GlobalConfig;
	import org.etherframework.tests.features.access.processors.ChildModuleProcessor;
	import org.etherframework.tests.features.access.processors.GlobalProcessor;
	import org.etherframework.tests.features.access.processors.Module2Processor;
	import org.etherframework.tests.features.access.processors.ModuleProcessor;
	import org.etherframework.tests.features.access.processors.TopModuleProcessor;
	import org.etherframework.tests.utils.ModuleInfo;
	import org.etherframework.tests.utils.TestUtility;
	import org.etherframework.wire.ProcessorFactory;
	import org.fluint.uiImpersonation.UIImpersonator;
	import org.hamcrest.assertThat;
	import org.hamcrest.object.notNullValue;
	import org.hamcrest.object.nullValue;
	
	import spark.components.Group;

	public class when_using_processor_global_access
	{
		private static var _testUtility:TestUtility = new TestUtility();
		private static var _globalView:Group;
		private static var _topModule:ModuleInfo;
		private static var _module:ModuleInfo;
		private static var _childModule:ModuleInfo;
		private static var _module2:ModuleInfo;
		private static var _globalModule:ModuleInfo;
		
		[BeforeClass]
		public static function setUpBeforeClass():void
		{
			const appDomain:ApplicationDomain = ApplicationDomain.currentDomain;
			_topModule = _testUtility.createModuleInfo(new GlobalConfig(), null, null, null, appDomain);
			_module = _testUtility.createModuleInfo(new GlobalConfig(), null, null, null, appDomain);
			_childModule = _testUtility.createModuleInfo(new GlobalConfig(), null, null, null, appDomain);
			_module2 = _testUtility.createModuleInfo(new GlobalConfig(), null, null, null, appDomain);
			_globalModule = _testUtility.createModuleInfo(new GlobalConfig(), null, null, null, appDomain);
			_globalView = UIImpersonator.addChild(new Group()) as Group;
			
			// Module hierarchical structure is view dependent. So as to resolve ancestor
			// module you need to address some ancestor view which hosts other module.
			_globalView.addElement(_topModule.module.view as IVisualElement);
			Group(_topModule.module.view).addElement(_module.module.view as IVisualElement);
			Group(_topModule.module.view).addElement(_module2.module.view as IVisualElement);
			Group(_module.module.view).addElement(_childModule.module.view as IVisualElement);
			
			_topModule.module.wiring.addProcessor(new ProcessorFactory(TopModuleProcessor, TopModuleProcessor.NAME));
			_module.module.wiring.addProcessor(new ProcessorFactory(ModuleProcessor, ModuleProcessor.NAME));
			_module2.module.wiring.addProcessor(new ProcessorFactory(Module2Processor, Module2Processor.NAME));
			_childModule.module.wiring.addProcessor(new ProcessorFactory(ChildModuleProcessor, ChildModuleProcessor.NAME));
			_globalModule.module.wiring.addProcessor(new ProcessorFactory(GlobalProcessor, GlobalProcessor.NAME));
		}
		
		[AfterClass]
		public static function tearDownAfterClass():void
		{
			_testUtility.dispose();
		}
		
		[Test(order=1)]
		public function when_getting_top_processor_it_should_be_resolved():void
		{
			assertThat(_topModule.bridge.facade.createProcessor(GlobalProcessor.NAME), notNullValue());
			assertThat(_topModule.bridge.facade.createProcessor(TopModuleProcessor.NAME), notNullValue());
			assertThat(_module.bridge.facade.createProcessor(TopModuleProcessor.NAME), notNullValue());
			assertThat(_childModule.bridge.facade.createProcessor(TopModuleProcessor.NAME), notNullValue());
		}
		
		[Test(order=2)]
		public function when_getting_module_processor_it_should_be_resolved():void
		{
			assertThat(_module.bridge.facade.createProcessor(GlobalProcessor.NAME), notNullValue());
			assertThat(_topModule.bridge.facade.createProcessor(ModuleProcessor.NAME), notNullValue());
			assertThat(_module.bridge.facade.createProcessor(ModuleProcessor.NAME), notNullValue());
			assertThat(_childModule.bridge.facade.createProcessor(ModuleProcessor.NAME), notNullValue());
		}
		
		[Test(order=3)]
		public function when_getting_child_processor_it_should_be_resolved():void
		{
			assertThat(_childModule.bridge.facade.createProcessor(GlobalProcessor.NAME), notNullValue());
			assertThat(_topModule.bridge.facade.createProcessor(ChildModuleProcessor.NAME), notNullValue());
			assertThat(_module.bridge.facade.createProcessor(ChildModuleProcessor.NAME), notNullValue());
			assertThat(_childModule.bridge.facade.createProcessor(ChildModuleProcessor.NAME), notNullValue());
		}
		
		[Test(order=4)]
		public function when_getting_processor_from_another_branch_it_should_be_resolved():void
		{
			assertThat(_module2.bridge.facade.createProcessor(GlobalProcessor.NAME), notNullValue());
			assertThat(_module2.bridge.facade.createProcessor(TopModuleProcessor.NAME), notNullValue());
			assertThat(_module2.bridge.facade.createProcessor(Module2Processor.NAME), notNullValue());
			assertThat(_module2.bridge.facade.createProcessor(ModuleProcessor.NAME), notNullValue());
		}
	}
}